package vip.web3.admin.job.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.jsoup.Connection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.web3j.utils.Convert;
import vip.web3.admin.sys.entity.biz.ARecordEntity;
import vip.web3.admin.sys.entity.biz.AUserEntity;
import vip.web3.admin.sys.entity.biz.AUserWalletEntity;
import vip.web3.admin.sys.redis.RedisConstant;
import vip.web3.admin.sys.service.biz.IAOrderService;
import vip.web3.admin.sys.service.biz.IARecordService;
import vip.web3.admin.sys.service.biz.IAUserService;
import vip.web3.admin.sys.service.biz.IAUserWalletService;
import vip.web3.api.dao.biz.RecordDao;
import vip.web3.api.dao.biz.UserDao;
import vip.web3.api.dao.biz.UserWalletDao;
import vip.web3.api.entity.base.SysConfigEntity;
import vip.web3.api.entity.biz.RecordEntity;
import vip.web3.api.entity.biz.UserEntity;
import vip.web3.api.entity.biz.UserWalletEntity;
import vip.web3.api.service.base.SysConfigApiService;
import vip.web3.api.service.base.Web3jApiService;
import vip.web3.api.service.impl.biz.UserServiceImpl;
import vip.web3.api.utils.Arith;
import vip.web3.common.enums.ActiveEnum;
import vip.web3.common.enums.AssetEnum;
import vip.web3.common.enums.OperateEnum;
import vip.web3.common.enums.user.TeamCountEnum;
import vip.web3.common.enums.user.TeamLevelEnum;
import vip.web3.common.exception.RRException;
import vip.web3.common.utils.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * @description: 商城定时任务
 * @author: YJY
 * @create: 2022-11-21 11:14
 **/
@Slf4j
@Component
@EnableScheduling
public class ApiBaseTask {

    @Resource
    private Web3jApiService web3jApiService;

    @Resource
    private SysConfigApiService sysConfigApiService;

    @Resource
    private IARecordService iARecordService;

    @Resource
    private IAOrderService iAOrderService;

    @Resource
    private IAUserService iAUserService;

    @Resource
    private IAUserWalletService iAUserWalletService;

    @Resource
    private RedisUtils redisUtils;
    @Resource
    private UserWalletDao userWalletDao;

    @Resource
    private RecordDao recordDao;
    @Resource
    private UserDao userDao;
    @Resource
    private UserServiceImpl userService;


    private static final List<String> server_address = new ArrayList();

    private static String usdtContractAddress = "0x55d398326f99059fF775485246999027B3197955";

    static {
        server_address.add("https://bsc-dataseed.binance.org");
        server_address.add("https://bsc-dataseed1.defibit.io");
    }

    private static String okChain = "https://endpoints.omniatech.io/v1/xlayer/mainnet/public";
    private static String okUsdtContractAddress = "0x1E4a5963aBFD975d8c9021ce480b42188849D41d";

    /**
     * 推荐奖励发放
     */
    @Scheduled(cron = "0/10 * * * * ?")
    public void inviteReward() {
        log.error("推荐奖励发放开始...");
        try {
            iAOrderService.inviteReward();
        } catch (Exception ex) {
            log.error("推荐奖励发放异常...");
        }
        log.error("推荐奖励发放结束...");
    }

    /**
     * 基础奖励 + 月度奖励 + 个人业绩奖励
     */
    @Scheduled(cron = "55 45 0 * * ?")
    public void userReward() {
        log.error("基础奖励发放开始...");
        try {
//            iAOrderService.baseReward();
        } catch (Exception ex) {
            log.error("基础奖励发放异常...");
        }
        log.error("基础奖励发放结束...");

        log.error("月度等级 + 业绩奖励发放开始...");
        try {
            iAUserService.teamReward();
        } catch (Exception ex) {
            log.error("月度等级 + 业绩奖励发放异常...");
        }
        log.error("月度等级 + 业绩奖励发放结束...");

        log.error("季度奖励发放开始...");
        try {
            //   iAUserService.quarterReward();
        } catch (Exception ex) {
            log.error("季度奖励发放异常...");
        }
        log.error("季度奖励发放结束...");
    }

    @Scheduled(cron = "15 0/1 * * * ? ")
    public void sermonCheck() {
        log.error("提现-充值检查开始...");
        String coldAddress = sysConfigApiService.getValue("cold_address");
        String hotAddress = sysConfigApiService.getValue("hot_address");
        String hotAddressKey = sysConfigApiService.getValue("hot_private_key");
        hotAddressKey = AES.encrypt("pYwPdQ1XYEVELgAHvpx/RA==", hotAddressKey);

        List<ARecordEntity> recharges = iARecordService.listRechargeRecord();
        List<ARecordEntity> withdraws = iARecordService.listWithdrawRecord();

        if (!CollectionUtils.isEmpty(recharges)) {
            for (ARecordEntity recharge : recharges) {
                int nextInt = RandomUtils.nextInt(server_address.size());
                String server = server_address.get(nextInt);
                try {
                    // 不足1分钟, 不检查
                    if (System.currentTimeMillis() - recharge.getCreateDate().getTime() < 60L * 1000L) {
                        continue;
                    }
                    // OKT USDT 充值
                    if (System.currentTimeMillis() - recharge.getCreateDate().getTime() > 60L * 60L * 1000L) {
                        recharge.setStatus(3);
                        recharge.setHash("充值时间超过1小时: " + recharge.getUserId());
                        iARecordService.updateById(recharge);
                    }
                    // 充值 1, 转 OKT 做手续费, 2, 将目标地址 USDT 转移至 冷钱包, 3, 充值数量, 以实际到账数量为准
                    AUserEntity user = iAUserService.getById(recharge.getUserId());
                    BigDecimal balanceUser = web3jApiService.getBalance(server, user.getBscAddress(), usdtContractAddress);
                    if (balanceUser != null
                            && balanceUser.setScale(2, RoundingMode.DOWN).compareTo(recharge.getAmount()) >= 0) {
                        String transferBnb = web3jApiService.imputationTransfer(server, "", user.getBscAddress(), BigInteger.ZERO, hotAddressKey, hotAddress);
                        log.error("BNB 手续费转账哈希: " + transferBnb);
                        if ("succeed".equals(transferBnb) || getTransactionResult(server, transferBnb, 0)) {
                            // 转完手续费之后, 执行归集操作
                            BigInteger amountUsd = new BigInteger(Convert.toWei(recharge.getAmount(), Convert.Unit.ETHER).setScale(0, RoundingMode.DOWN).toPlainString());
                            String transferUsd = web3jApiService.imputationTransfer(server, usdtContractAddress, coldAddress, amountUsd, user.getBscPrivate(), user.getBscAddress());
                            log.error("USDT 归集转账哈希: " + transferUsd);

                            if (getTransactionResult(server, transferUsd, 0)) {
                                // 修改状态
                                recharge.setHash(transferUsd);
                                recharge.setStatus(1);
                                iARecordService.updateById(recharge);

                                AUserWalletEntity wallet = iAUserWalletService.findByUserId(recharge.getUserId());
                                iAUserWalletService.updateWallet(wallet, AssetEnum.TYPE2.getCode(), recharge.getAmount(), BigDecimal.ZERO);
                                wallet = iAUserWalletService.findByUserId(recharge.getUserId());
                                wallet.setType(2);
                                iAUserWalletService.updateById(wallet);
                                log.error(recharge.getAddress() + " BNB usdt 充值归集成功... " + balanceUser.stripTrailingZeros().toPlainString());
                            }
                        }
                    }
                } catch (Exception ex) {
                    log.error("充值检查处理异常: " + recharge.getAddress());
                }
            }
        }

        if (!CollectionUtils.isEmpty(withdraws)) {
            for (ARecordEntity withdraw : withdraws) {
                // 提现
                BigDecimal amount = withdraw.getAmount();
                BigDecimal fee = withdraw.getFee();
                amount = amount.subtract(fee);

                String addr = withdraw.getAddress();
                try {
                    // 提现
                    int nextInt = RandomUtils.nextInt(server_address.size());
                    String server = server_address.get(nextInt);

                    if (withdraw.getRemark().contains("X Layer Chain")) {
                        BigDecimal balance = web3jApiService.getXLayerBalance(okChain, hotAddress, okUsdtContractAddress);
                        log.error("X Layer: 热钱包 余额 " + balance.toPlainString());

                        if (balance == null || amount.compareTo(balance) > 0) {
                            log.error("X Layer: 热钱包 余额不足!");
                            return;
                        }
                        BigInteger amount_ = new BigInteger(Convert.toWei(amount, Convert.Unit.MWEI).setScale(0, RoundingMode.DOWN).toPlainString());
                        String hash = web3jApiService.imputationTransfer(okChain, okUsdtContractAddress, addr, amount_, hotAddressKey, hotAddress);

                        if (getTransactionResult(okChain, hash, 0)) {
                            withdraw.setHash(hash);
                            withdraw.setStatus(1);
                            iARecordService.updateById(withdraw);
                            log.error(withdraw.getAddress() + ", USDT 提现成功... " + amount.stripTrailingZeros().toPlainString());
                        }
                    } else {
                        BigDecimal balance = web3jApiService.getBalance(server, hotAddress, usdtContractAddress);
                        log.error("BSC: 热钱包 余额 " + balance.toPlainString());

                        if (balance == null || amount.compareTo(balance) > 0) {
                            log.error("BSC: 热钱包 余额不足!");
                            return;
                        }

                        BigInteger amount_ = new BigInteger(Convert.toWei(amount, Convert.Unit.ETHER).setScale(0, RoundingMode.DOWN).toPlainString());
                        String hash = web3jApiService.imputationTransfer(server, usdtContractAddress, addr, amount_, hotAddressKey, hotAddress);

                        if (getTransactionResult(server, hash, 0)) {
                            withdraw.setHash(hash);
                            withdraw.setStatus(1);
                            iARecordService.updateById(withdraw);
                            log.error(withdraw.getAddress() + ", USDT 提现成功... " + amount.stripTrailingZeros().toPlainString());
                        }
                    }
                } catch (Exception ex) {
                    withdraw.setStatus(3);
                    iARecordService.updateById(withdraw);
                    log.error("提现处理异常: " + withdraw.getAddress() + " " + ex.getMessage());
                }
            }
        }

        log.error("提现-充值检查结束...");
    }

    private boolean getTransactionResult(String server,
                                         String transactionHash,
                                         int num) throws InterruptedException, ExecutionException {
        if (num > 9) {
            throw new RRException("mints失败,当前交易上链失败:" + transactionHash);
        }

        Boolean transactionResult = this.web3jApiService.getTransactionResult(server, transactionHash);
        if (transactionResult == null) {
            Thread.sleep(3000L);
            num++;
            return getTransactionResult(server, transactionHash, num);
        }
        return transactionResult.booleanValue();
    }

    /**
     * 每分钟执行一次
     *
     * @param
     */
    @Scheduled(cron = "0 0/5 * * * ?")
    public void checkOrderStatus() {
        log.error("我是每分钟执行一次的order................................................");
        iAOrderService.baseReward();
    }

    public static void main(String[] args) {
        try {
            String key = "t9g23Y2OxzTtV++fRlycI0XAjdvtnvUDTb8HlXa/AMCDdmweVt3jXaVLea0T3jUuDBlS4wgZz3cVbdBImvRhciJfUsaSUFHVAClNCl+5TTo=";
            String decrypt = AES.decrypt("pYwPdQ1XYEVELgAHvpx/RA==", "jcQ1wRNclh7TTWMcdqHiDiLKN2vGI7P8BrT1VE4TFQdekRwv8gmUW3fZhNMcc/81ZqCDg+++7VzjFKIpxHc3viJfUsaSUFHVAClNCl+5TTo=");
            System.out.println(key);
            System.out.println(decrypt);
        } catch (Exception ex) {

        }
    }


}
